<?php
class PaginatorComponent extends Object {
	
	var $Controller;
	
	function startup(&$controller) {
		$this->Controller = $controller;
		$this->params	  =& $controller->params;
		$this->passedArgs =& $controller->passedArgs;
		$this->paginate   =& $controller->paginate;
	}
/**
 * Handles automatic pagination of model records.
 *
 * @param mixed $object Model to paginate (e.g: model instance, or 'Model', or 'Model.InnerModel')
 * @param mixed $scope Conditions to use while paginating
 * @param array $whitelist List of allowed options for paging
 * @return array Model query results
 * @access public
 */
	function paginate(&$object = null) {
		if (!is_object($object)) {
			trigger_error(sprintf(__('Paginator::paginate() - can\'t find model %1$s in controller %2$sController', true), $object, $this->Controller->name), E_USER_WARNING);
			return array();
		}
		$options = array_merge($this->params, $this->params['url'], $this->passedArgs);
		

		if (isset($this->paginate[$object->alias])) {
			$defaults = $this->paginate[$object->alias];
		} else {
			$defaults = $this->paginate;
		}
		
		if (!isset($defaults['prefix'])) {
			$defaults['prefix'] = '';
		}

		if (isset($options[$defaults['prefix'] . 'show'])) {
			$options['limit'] = $options[$defaults['prefix'] . 'show'];
		}

		if (isset($options[$defaults['prefix'] . 'sort'])) {
			$direction = null;
			if (isset($options[$defaults['prefix'] . 'direction'])) {
				$direction = strtolower($options[$defaults['prefix'] . 'direction']);
			}
			if ($direction != 'asc' && $direction != 'desc') {
				$direction = 'asc';
			}
			$options['order'] = array($options[$defaults['prefix'] . 'sort'] => $direction);
		}

		if (!empty($options['order']) && is_array($options['order'])) {
			$alias = $object->alias ;
			$key = $field = key($options['order']);

			if (strpos($key, '.') !== false) {
				list($alias, $field) = explode('.', $key);
			}
			$value = $options['order'][$key];
			unset($options['order'][$key]);

			if (isset($object->{$alias}) && $field = $object->{$alias}->hasField($field)) {
				$options['order'][$alias . '.' . $field] = $value;
			} elseif ($field = $object->hasField($field)) {
				$options['order'][$alias . '.' . $field] = $value;
			}
		}
		
		if (isset($options[$defaults['prefix'] . 'page'])) {
			$options['page'] = $options[$defaults['prefix'] . 'page'];
		}
		
		$vars = array('fields', 'order', 'limit', 'page', 'recursive', 'group', 'expects');
		$keys = array_keys($options);
		$count = count($keys);
		
		for ($i = 0; $i < $count; $i++) {
			if (!in_array($keys[$i], $vars)) {
				unset($options[$keys[$i]]);
			}
			if ($keys[$i] === 'fields' || $keys[$i] === 'recursive') {
				unset($options[$keys[$i]]);
			}
			if (is_numeric($keys[$i])) {
				unset($options[$keys[$i]]);
			}
		}
		$conditions = $fields = $order = $limit = $page = $recursive = $group = null;
		$expects = false;
		
		if (!isset($defaults['conditions'])) {
			$defaults['conditions'] = array();
		}
				
		extract($options = array_merge(array('page' => 1, 'limit' => 20), $defaults, $options));
		
		if ($recursive === null) {
			$recursive = $object->recursive;
		}
		
		$extra = array_diff_key($defaults, compact('conditions', 'fields', 'order', 'limit', 'page', 'recursive', 'group'));
		
		if ($expects !== false) {
			$object->expects($expects);
		}
		if (method_exists($object, 'paginateCount')) {
			$parameters = compact('conditions');
			$count = $object->paginateCount(array_merge($parameters, $extra, array('group' => $group,'recursive' => $recursive)));
		} else {
			$parameters = compact('conditions');
			/*if ($recursive != $object->recursive) {
				$parameters['recursive'] = $recursive;
			}*/
			$count = $object->findCount(array_merge($parameters, $extra, array('group' => $group,'recursive' => $recursive)));
		}
		$pageCount = intval(ceil($count / $limit));
		
		if ($page === 'last' || $page >= $pageCount) {
			$options['page'] = $page = $pageCount;
		} elseif (intval($page) < 1) {
			$options['page'] = $page = 1;
		}
		
		if ($expects !== false) {
			$object->expects($expects);
		}
		if (method_exists($object, 'paginate')) {
			$results = $object->paginate($conditions, $fields, $order, $limit, $page, $recursive, $group);
		} else {
			/*$parameters = compact('conditions', 'fields', 'order', 'limit', 'page');
			if ($recursive != $object->recursive) {
				$parameters['recursive'] = $recursive;
			}
			$parameters = array_merge($parameters, $extra);*/
			$results = $object->findAll($conditions, $fields, $order, $limit, $page, $recursive, $group);
		}
		
		//$options['object'] =& $object;
		
		$paging = array(
			'page'		=> $page,
			'current'	=> count($results),
			'count'		=> $count,
			'prevPage'	=> ($page > 1),
			'nextPage'	=> ($count > ($page * $limit)),
			'pageCount'	=> $pageCount,
			'defaults'	=> array_merge(array('limit' => 20, 'step' => 1), $defaults),
			'options'	=> $options,
			'object'	=> &$object,
			'prefix'	=> $defaults['prefix']
		);
		$this->params['paging'][(!empty($defaults['prefix']) ? $defaults['prefix'] : $object->alias)] = $paging;

		if (!in_array('Paginator', $this->Controller->helpers) && !isset($this->Controller->helpers['Paginator'])) {
			$this->Controller->helpers[] = 'Paginator';
		}
		return $results;
	}
}
?>